package com.hb.repository;

import com.hb.Order;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;

import java.util.List;

/**
 * 因为 OrderRepository 扩展了 MongoRepository，因此它就会传递性地扩展 Repository 标记接口，任何扩展 Repository 的接口将会在运行时自动生成实现。
 * 所以会为 OrderRepository 生成读取和写入数据到 MongoDB 文档数据库的实现。
 * MongoRepository 接口有两个参数，第一个是带有 @Document 注解的对象类型，也就是该 Repository 要处理的类型。第二个参数是带有 @Id 注解的属性类型。
 * 尽管 OrderRepository 本身并没有定义任何方法，但是它会继承多个方法，包括对 Order 文档进行 CRUD 操作的方法。下面描述了 OrderRepository 继承的所有方法。
 * 1、long count();返回指定Repository类型的文档数量
 * 2、void delete(Iterable<？ extends T);删除与指定对象关联的所有文档
 * 3、void delete(T);删除与指定对象关联的文档
 * 4、void delete(ID);根据 ID 删除某一个文档
 * 5、void deleteAll();删除指定 Repository 类型的所有文档
 * 6、boolean exists(Object);如果存在与指定对象相关联的文档，则返回 true
 * 7、boolean exists(ID);如果存在指定 ID 的文档，则返回 true
 * 8、List<T> findAll();返回指定 Repository 类型的所有文档
 * 9、List<T> findAll(Iterable<ID>);返回指定文档 ID 对应的所有文档
 * 10、List<T> findAll(Sort);为指定的 Repository 类型，返回排序后的所有文档列表
 * 11、T findOne(ID);为指定的 ID 返回单个文档
 * 12、Save(Iterable<s>);保存指定 Iterable 中的所有文档
 * 13、save ( < S > );为给定的对象保存一条文档
 */
public interface OrderRepository extends MongoRepository<Order, String>, OrderOperations {
    // 我们学习了 Spring Data JPA 支持方法命名约定，它能够帮助 Spring Data 为遵循约定的方法自动生成实现。
    // 实际上，相同的约定也适用于 Spring Data MongoDB。这意味着我们可以为 OrderRepository 添加自定义的方法。

    // 获取 customer 属性等于传入值的 Order 列表
    List<Order> findByCustomer(String c);

    // 获取 customer 属性like传入值的Order列表
    List<Order> findByCustomerLike(String c);

    // 返回 customer 和 type 属性等于传入值的 Order 对象
    List<Order> findByCustomerAndType(String c, String t);

    // 最后一个方法与前一个类似，只不过 customer 在对比的时候使用的是 like 而不是 equals
    List<Order> findByCustomerLikeAndType(String c);

    // @Query 注解可以为 Repository 方法指定自定义的查询。@Query 能够像在 JPA 中那样用在 MongoDB 上。唯一的区别在于针对 MongoDB 时，
    // @Query 会接受一个 JSON 查询，而不是 JPA 查询。
    // 例如，假设我们想要查询给定类型的订单，并且要求 customer 的名称为 “Chuck Wagon”。OrderRepository 中如下的方法声明能够完成所需的任务：
    // @Query 中给定的 JSON 将会与所有的 Order 文档进行匹配，并返回匹配的文档。需要注意的是，type 属性映射成了 “?0”，这表明 type 属性应该与查询方法的第零个参数相等（也就是方法参数 t）。
    // 如果有多个参数的话，它们可以通过 “?1”、“?2” 等方式进行引用。
    @Query("{'customer': 'Chuck Wagon', 'type':?0}")
    List<Order> findChucksOrders(String t);
}
